using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using FrameWork.Managers;
using UnityEngine;

namespace FrameWork
{
    [DisallowMultipleComponent]
    public class GameManager : MonoBehaviour
    {
        public static GameManager Instance => _instance;

        private static GameManager _instance;

        public ResourcesManager ResourcesManager { get; private set; }
        
        public UIManager UIManager { get; private set; }

        private void Awake()
        {
            Application.targetFrameRate = 60;
            Application.runInBackground = true;

            _instance = this;
            DontDestroyOnLoad(this);
        }

        private readonly List<IManager> _managers = new();

        private void CreateManagers()
        {
            ResourcesManager = new ResourcesManager();
            _managers.Add(this.ResourcesManager);
            
            UIManager = new UIManager();
            _managers.Add(UIManager);
        }
        
        #region 生命周期

        public async UniTask InitGame()
        {
            //创建管理器
            CreateManagers();
            
            //初始化步骤1 检查属性，初始化必要设置
            List<UniTask> tasks = Enumerable.Select(_managers, manager => manager.OnInitStart()).ToList();
            await UniTask.WhenAll(tasks);
            
            tasks.Clear();
            //初始化步骤2 检查资源，初始化各种加载，网络，配置，资源，更新等等
            tasks = Enumerable.Select(_managers, manager => manager.OnInit()).ToList();
            await UniTask.WhenAll(tasks);
            
            tasks.Clear();
            //初始化步骤3，如果有资源依赖于其他管理器的步骤2完成就放在步骤3中
            tasks = Enumerable.Select(_managers, manager => manager.OnInitEnd()).ToList();
            await UniTask.WhenAll(tasks);

            StartGame();
        }

        private void StartGame()
        {
            foreach (var manager in _managers)
            { 
                manager.OnStart();
            }
            
            // LaunchController.
        }

        private void Update()
        {
            foreach (var manager in _managers)
            { 
                manager.OnUpdate();
            }
        }

        private void OnDestroy()
        {
            foreach (var manager in _managers)
            { 
                manager.OnRelease();
            }
        }

        #endregion
        
    }
}
